package com.ylx.mybatis.utils;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.ReflectUtil;

import java.lang.reflect.Field;
import java.util.List;
import java.util.Objects;

/**
 * 生成sql工具类
 * @author yanglixin
 */
public final class SqlCreateUtil {

    /**
     * 生成删除的语句
     * 输入表名和要删除的id集合
     * @author yanglixin
     */
    public static <T> String deleteByIdListSql(String tableName, String idFieldName, List<T> needDeleteIds) {
        if (CollUtil.isEmpty(needDeleteIds)) {
            return "";
        }
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append(String.format("DELETE FROM `%s` WHERE `%s` IN (",tableName,idFieldName));
        int size = needDeleteIds.size();
        for (int i = 0; i < needDeleteIds.size(); i++) {
            T id = needDeleteIds.get(i);
            stringBuilder.append(id);
            if (i < size - 1) {
                stringBuilder.append(",");
            }
        }
        stringBuilder.append(");");

        return stringBuilder.toString();
    }

    /**
     * 生成根据id修改的sql语句
     * @author yanglixin
     */
    public static <T, I> String updateByIdSql(T entity, String idFieldName) {
        I id = (I) ReflectUtil.getFieldValue(entity, idFieldName);
        StringBuilder columns = new StringBuilder();

        Field[] fields = entity.getClass().getDeclaredFields();

        for (Field field : fields) {
            if (CharSequenceUtil.equals(idFieldName,field.getName())) {
                continue;
            }
            String columnName = camelToSnake(field.getName());
            Object value = ReflectUtil.getFieldValue(entity,field);
            if (Objects.isNull(value)) {
                continue;
            }
            if (columns.length() > 0) {
                columns.append(", ");
            }
            columns.append("`").append(columnName).append("`").append("=").append(formatValue(value));
        }

        String tableName = camelToSnake(entity.getClass().getSimpleName());
        if (columns.length() == 0) {
            return "";
        }
        return String.format("UPDATE `%s` SET %s WHERE `%s`=%s;", tableName, columns, idFieldName, formatValue(id));
    }

    private static String formatValue(Object value) {
        if (value instanceof String) {
            return "'" + value.toString().replace("'", "''") + "'";
        } else if (value instanceof Number) {
            return value.toString();
        } else {
            return "'" + value.toString().replace("'", "''") + "'";
        }
    }

    /**
     * 更具实体类生成插入的sql语句
     * 表明使用类名转下划线,当某个字段为null时不生成对应的插入
     * @param entity 要插入的实体类
     * @return 插入的sql语句
     */
    public static <T> String generateInsertSql(T entity) {
        StringBuilder columns = new StringBuilder();
        StringBuilder values = new StringBuilder();

        Field[] fields = entity.getClass().getDeclaredFields();
        for (Field field : fields) {
            String columnName = camelToSnake(field.getName());

            Object value = ReflectUtil.getFieldValue(entity,field);

            if (Objects.isNull(value) && !(CharSequenceUtil.equals("create_time",columnName) || CharSequenceUtil.equals("update_time",columnName))) {
                //当value为空时跳过
                continue;
            }

            if (columns.length() > 0) {
                columns.append(", ");
                values.append(", ");
            }
            columns.append("`").append(columnName).append("`");

            if (CharSequenceUtil.equals("create_time",columnName) || CharSequenceUtil.equals("update_time",columnName)) {
                //时间设置为now
                values.append("now()");
            } else {
                values.append("'").append(value).append("'");
            }
        }

        String tableName = camelToSnake(entity.getClass().getSimpleName());
        return String.format("INSERT INTO %s (%s) VALUES (%s);", tableName, columns, values);
    }

    /**
     * 将驼峰命名或大驼峰命名格式转换为下划线命名格式
     *
     * @author yanglixin
     */
    public static String camelToSnake(String camelCase) {
        StringBuilder result = new StringBuilder();
        result.append(Character.toLowerCase(camelCase.charAt(0)));
        for (int i = 1; i < camelCase.length(); i++) {
            char ch = camelCase.charAt(i);
            if (Character.isUpperCase(ch)) {
                result.append('_');
                result.append(Character.toLowerCase(ch));
            } else {
                result.append(ch);
            }
        }
        return result.toString();
    }

    private SqlCreateUtil() {}
}
